package com.cabal.common.util;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.apache.commons.lang.StringUtils;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.Map.Entry;

/**
 * Json工具类
 * 
 * @author shenkang
 * @date 2022年11月24日
 */
public class CabalJsonUtil {

	private final static ObjectMapper objectMapper = new ObjectMapper();

	private CabalJsonUtil() {
	}
	
	static{
		objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
//		objectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
		
		objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
	}

	public static ObjectMapper getInstance() {

		return objectMapper;
	}

	/**
	 * javaBean,list,array convert to json string
	 */
	public static String obj2json(Object obj) throws Exception {
		return objectMapper.writeValueAsString(obj);
	}

	/**
	 * json string convert to javaBean
	 */
	public static <T> T json2pojo(String jsonStr, Class<T> clazz) {
		try {
			return objectMapper.readValue(jsonStr, clazz);
		} catch (Exception e) {

		}
		return null;
	}

	/**
	 * json string convert to map
	 */
	public static <T> Map<String, Object> json2map(String jsonStr)
			throws Exception {
		return objectMapper.readValue(jsonStr, Map.class);
	}

	/**
	 * json string convert to map with javaBean
	 */
	public static <T> Map<String, T> json2map(String jsonStr, Class<T> clazz)
			throws Exception {
		Map<String, T> map = objectMapper.readValue(jsonStr,
				new TypeReference<Map<String, T>>() {
				});
		Map<String, T> result = new HashMap<String, T>();
		for (Entry<String, T> entry : map.entrySet()) {
			result.put(entry.getKey(), map2pojo((Map)entry.getValue(), clazz));
		}
		return result;
	}

	/**
	 * json array string convert to list with javaBean
	 */
	public static <T> List<T> json2list(String jsonArrayStr, Class<T> clazz)
			throws Exception {
		List<T> list = objectMapper.readValue(jsonArrayStr,
				new TypeReference<List<T>>() {
				});
		List<T> result = new ArrayList<T>();
		for (T map : list) {
			result.add(map2pojo((Map)map, clazz));
		}
		return result;
	}

	/**
	 * map convert to javaBean
	 */
	public static <T> T map2pojo(Map map, Class<T> clazz) {
		return objectMapper.convertValue(map, clazz);
		
	}

	/**
	 * javaBean convert to map
	 */
	public static <T> T javaBeanToMap(Object object, Class<T> clazz) {
		return objectMapper.convertValue(object, clazz);
	}

	public static String pojoToKeyAndValue(Object object, List<String> excludeKeys, boolean isAllowNull) {
		StringBuffer sbkey = new StringBuffer();
		try {
			String jsonData = obj2json(object);
			Map<String, Object> mapData = json2map(jsonData);
			if(!CollectionUtils.isEmpty(excludeKeys)) {
				for(String excludeKey : excludeKeys) {
					mapData.remove(excludeKey);
				}
			}

			if(!isAllowNull) {
				for(Entry<String, Object> entry : mapData.entrySet()){
					if(entry.getValue() == null) {
						mapData.remove(entry.getKey());
					}
				}
			}
			return sortString(mapData, "", "");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return sbkey.toString();
	}

	/**
	 * 不参与签名逻辑的参数
	 */
	private static String[] params = {"sign", "session"};

	/**
	 * 单条数据转json的参数
	 */
	private static String[] singleParams = {"sender","receiver"};

	/**
	 * 集合数据转json的参数
	 */
	private static String[] doubleParams = {"goods","entry_arr","goods_list"};

	/**
	 * 组合String
	 *
	 * @param map
	 * @return
	 */
	public static String sortString(Map<String, Object> map, String connectSymbol, String connectSymbol2) {

		String str = "";

		List<String> list = new ArrayList<String>();
		//将key值放入List集合中
		if (map != null) {
			for (Entry<String, Object> entry : map.entrySet()) {
				list.add(entry.getKey());
			}
		}
		//将key集合转化为数组
		String[] input = new String[list.size()];
		for (int i = 0; i < list.size(); i++) {
			input[i] = list.get(i);
		}
		//进行排序
		Arrays.sort(input);

		for (int i = 0; i < input.length; i++) {
			String key = input[i];
			//判断其value值是否为map
			Object value = map.get(input[i]);

			if(TmsStringUtils.contains(singleParams, key)) {
				str += (key + sortString((Map<String, Object>) value, connectSymbol, connectSymbol2));
			} else if(TmsStringUtils.contains(doubleParams, key)) {
				ArrayList goodsList = (ArrayList) value;
				str +=key;
				for (int j = 0; j < goodsList.size(); j++) {
					Map goodsMap = (Map) goodsList.get(j);
					str += (j + sortString(goodsMap, connectSymbol, connectSymbol2));
				}
			}else {
				boolean isOut = false;

				for (int j = 0; j < params.length; j++) {
					if (key.equals(params[j])) {
						isOut = true;
						break;
					}
				}

				if (!isOut) {
					str += key + connectSymbol + value + connectSymbol2;
				}
			}

		}

		if(StringUtils.isNotBlank(connectSymbol2)) {
			return str.substring(0, str.length() - 1);
		}
		return str;
	}

	public static String objToStringKeyAndValue(Object object) throws Exception {
		String jsonData = obj2json(object);
		Map<String, Object> mapData = json2map(jsonData);
		StringBuffer sbkey = new StringBuffer();


		for (Entry<String, Object> item : mapData.entrySet()) {
			String k = item.getKey();
			Object v = item.getValue();
			if(null != v && !"".equals(v)) {
				sbkey.append(k + "=" + v + "&");
			}
		}
		return sbkey.toString().substring(0, sbkey.length() - 1);
	}

	public static String pojoShortToString(Object object, List<String> excludeKeys) {
		StringBuffer sbkey = new StringBuffer();
		try {
			String jsonData = obj2json(object);
			Map<String, Object> mapData = json2map(jsonData);
			if(!CollectionUtils.isEmpty(excludeKeys)) {
				for(String excludeKey : excludeKeys) {
					mapData.remove(excludeKey);
				}
			}

			return sortString(mapData, "=", "&");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return sbkey.toString();
	}

	/**
	 * 对参数按照Key进行ASCII排序
	 *
	 * @param jsonParam 请求参数
	 * @return 排序拼装后的字符串
	 */
	public static String getSortedString(String jsonParam) {
		String resultJson = null;
		try {
			Map<String, Object> jsonMap = CabalJsonUtil.json2map(jsonParam);
			List<String> keys = new ArrayList<String>(jsonMap.keySet());
			Collections.sort(keys);
			keys.remove("sign");
			LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
			for(int i=0;i<keys.size();i++){
				if(StringUtils.isNotEmpty(keys.get(i))){
					if(jsonMap.get(keys.get(i)) == null || jsonMap.get(keys.get(i)) == "") {
						continue;
					}
					map.put(keys.get(i), jsonMap.get(keys.get(i)).toString());
				}
			}
			resultJson = CabalJsonUtil.map2pojo(map, JSONObject.class).toString();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return resultJson;
	}


//	public static void main(String[] arg0){
//		String str = "{\"a\":\"a\",\"b\":\"b\"}";
//		obj2json
//		
//	}
}
